package com.xuzhiguang.lightnat.common.codec;

import com.xuzhiguang.lightnat.common.constant.NatMessageConstants;
import com.xuzhiguang.lightnat.common.message.NatMessage;
import com.xuzhiguang.lightnat.common.message.NatMessageHeader;
import com.xuzhiguang.lightnat.common.message.NatMessageTypeEnum;
import com.xuzhiguang.lightnat.common.serializer.NatMessageSerializer;
import com.xuzhiguang.lightnat.common.serializer.SerializerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public class NatMessageDecoder extends MessageToMessageDecoder<ByteBuf> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {

        // decode header
        NatMessageHeader header = new NatMessageHeader();
        header.setMagic(byteBuf.readShort());
        if (NatMessageConstants.MAGIC != header.getMagic()) {
            throw new IllegalArgumentException("magic number is illegal. magic number: '" + header.getMagic() + "'");
        }
        header.setVersion(byteBuf.readByte());
        header.setSerializerType(byteBuf.readByte());
        header.setMessageType(byteBuf.readShort());
        header.setRequestId(byteBuf.readLong());

        // decode body
        byte[] bodyData = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bodyData);

        NatMessageSerializer serializer = SerializerFactory.getSerializer(header.getSerializerType());
        NatMessageTypeEnum typeEnum = NatMessageTypeEnum.findByType(header.getMessageType());
        if (typeEnum == null) {
            throw new IllegalArgumentException("message type is illegal. message type: '" + header.getMessageType() + "'");
        }

        NatMessage natMessage = new NatMessage();
        natMessage.setHeader(header);
        natMessage.setBody(serializer.deserialize(bodyData, typeEnum.getCls()));


        list.add(natMessage);
    }
}
